package main

import (. "./tabuleiro"; . "./util"; . "fmt"; . "./pecaPkg")

const( MAXIMO_CAMINHOS int = 50)

func TomadaMaximaPeca(tabuleiro *Tabuleiro, posX int, posY int, cor int) ([MAXIMO_CAMINHOS] *Node, int) {
	var caminhosMaximos [MAXIMO_CAMINHOS] *Node
	var contador int = 0
	caminhos := tabuleiro.GetOpcoesComida(posX, posY, cor)
	tamanhoMaiorCaminho := 0
	tamanhoCaminhoTupla := 0
	var pilha *Node = nil	
	var caminhoAtual [MAXIMO_CAMINHOS] *Node
	var nodeAtual *Node // Topo da Pilha depois de verificar a melhor jogada
	var tuplaAtual *Tupla // valor do topo da pilha antes de verificar
	
	for i:=0; i < len(caminhos); i++ {
		if(caminhos[i].Comer){
		
			if(pilha != nil){
				newNode := new(Node)
				newNode.SetValor(&caminhos[i])
				newNode.Push(pilha)
				
			}else{
				pilha = new(Node)
				pilha.SetValor(&caminhos[i])
			}
		}
	}
	
	for ;pilha != nil; {
		tabTemp := tabuleiro.Copy()
		pilha, tuplaAtual = pilha.Pull()
		tabTemp.ComerPeca(posX, posY, tuplaAtual, cor)
		caminhoAtual, tamanhoCaminhoTupla = TomadaMaximaPeca(tabTemp, tuplaAtual.FicarX, tuplaAtual.FicarY, cor)
		tamanhoCaminhoTupla++ //Adiciona com o da tuplaAtual
		
		if(tamanhoCaminhoTupla >= tamanhoMaiorCaminho){
			if(tamanhoCaminhoTupla > tamanhoMaiorCaminho){
				tamanhoMaiorCaminho = tamanhoCaminhoTupla 
				contador = 0
				caminhosMaximos = *new([MAXIMO_CAMINHOS] *Node)
			}
			
			
			for i:=0; caminhoAtual[i] != nil && i < MAXIMO_CAMINHOS; i++ {
				nodeAtual = new(Node)
				nodeAtual.SetValor(tuplaAtual)
				caminhoAtual[i].Push(nodeAtual)
				caminhosMaximos[contador] = nodeAtual
				contador++
			}
			
			if(caminhoAtual[0] == nil){
				nodeAtual = new(Node)
				nodeAtual.SetValor(tuplaAtual)
				caminhosMaximos[contador] = nodeAtual
				contador++
			}
			
		}
	}
	
	return caminhosMaximos, tamanhoMaiorCaminho
}

func main() {
	
	Println("init")
	tab := new(Tabuleiro)
	tab.PreencherTabuleiro()
	//tab.MoverPeca (2, 2, 3, 3, 0 ,true)
	//tab.MoverPeca (2, 6, 3, 5, 0 ,true)
	//tab.MoverPeca (1, 5, 2, 6, 0 ,true)
	//tab.MoverPeca (3, 3, 4, 4, 0 ,true)
	//tab.MoverPeca (0, 4, 1, 5, 0 ,true)
	//tab.MoverPeca (3, 5, 4, 6, 0 ,true)
	//tab.MoverPeca (2, 6, 3, 7, 0 ,true)
	//tab.DeletarPeca(1,1)
	//tab.DeletarPeca(0,4)
	//tab.DeletarPeca(2,4)
	//tab.MoverPeca (2, 6, 3, 7, 0 ,true)
	//tab.MoverPeca (3, 5, 4, 4, 0 ,true)
	//tab.SetPecaDama(5,5)
	//tab.ImprimeTabuleiro()
	cor := 0
	for i:=0; i < 51 ; i++ {
		MelhorJogada(tab, cor)
		tab.ImprimeTabuleiro()
		cor = Inverter(cor) 
	}
}
     

func iniciarJogo(){


}

func finalizarPartida(){


}

func JogadaObrigatoria(tabuleiro *Tabuleiro, cor int) ([MAXIMO_CAMINHOS] *Node, [MAXIMO_CAMINHOS] *Tupla, int){
	
	var maiorTomada [MAXIMO_CAMINHOS] *Node
	var pecasTomada [MAXIMO_CAMINHOS] *Tupla
	pecas := tabuleiro.GetPecas(cor)
	maiorTamanhoTomada := 0
	contador := 0
	
	for i:=0; i < len(pecas) && pecas[i] != nil; i++ {
		tomada, tamanho := TomadaMaximaPeca(tabuleiro, pecas[i].X, pecas[i].Y, cor)
		if(tamanho >= maiorTamanhoTomada) {
			
			if(tamanho > maiorTamanhoTomada) {
				maiorTomada = *new([MAXIMO_CAMINHOS] *Node)
				pecasTomada = *new([MAXIMO_CAMINHOS] *Tupla)
				maiorTamanhoTomada = tamanho
				contador = 0
			}
			
			for j:=0 ; j < MAXIMO_CAMINHOS && contador < MAXIMO_CAMINHOS && tomada[j] != nil; j++ {
				maiorTomada[contador] = tomada[j]
				pecasTomada[contador] = pecas[i]				
				contador++
			}
		}
	}	
	return maiorTomada, pecasTomada, maiorTamanhoTomada
}


func isJogadaObrigatoria () {


}

func RealizarTomada(tabuleiro *Tabuleiro, posX int, posY int, tomada *Node, cor int) {

	var tuplaAtual *Tupla
	topo := tomada
	Print(">>> Peças comidas: ")
	x, y := posX, posY
	Print("(", x, y, ")")
	for topo != nil {
		topo, tuplaAtual = topo.Pull()
		tabuleiro.ComerPeca(x, y, tuplaAtual, cor)
		x, y = tuplaAtual.FicarX, tuplaAtual.FicarY 
		Print("-> (", x, y, ")")
	}
	Println("")
	tabuleiro.ViraDama(x, y, cor)
}


func MelhorJogada(tabuleiro *Tabuleiro, cor int) bool {

	tomadas, pecasTomadas, tamanhoTomada := JogadaObrigatoria(tabuleiro, cor)
	
	if(tamanhoTomada > 0){
		
		//Procura a tomada que permite que o adversario coma menos.
		tabuleiroTemp := tabuleiro.Copy()
		RealizarTomada(tabuleiroTemp, pecasTomadas[0].X, pecasTomadas[0].Y, tomadas[0], cor)
		_, _, menorTomadaAdversario := JogadaObrigatoria(tabuleiroTemp, Inverter(cor))
		melhorTomada := tomadas[0]
		pecaX := pecasTomadas[0].X
		pecaY := pecasTomadas[0].Y
		
		for i:=1; i < MAXIMO_CAMINHOS && tomadas[i] != nil; i++ {
			tabuleiroTemp = tabuleiro.Copy()
			RealizarTomada(tabuleiroTemp, pecasTomadas[i].X, pecasTomadas[i].Y, tomadas[i], cor)
			_, _, tomadaAdversario := JogadaObrigatoria(tabuleiroTemp, Inverter(cor))
			
			if(tomadaAdversario < menorTomadaAdversario){
				menorTomadaAdversario = tomadaAdversario
				melhorTomada = tomadas[i]
				pecaX = pecasTomadas[i].X
				pecaY = pecasTomadas[i].Y
			}
		}
		
		//Realiza a melhor Tomada
		Println(">>> A seguinte tomada foi realizada:")
		RealizarTomada(tabuleiro, pecaX, pecaY, melhorTomada, cor)
		return true
	}else {
		
		movimentos := tabuleiro.GetMovimentos(cor)
		tabTemp := tabuleiro.Copy()
		melhorMovimento := movimentos[0]
		viraDama := false
		tabTemp.MoverPeca(movimentos[0].X, movimentos[0].Y, movimentos[0].FicarX, movimentos[0].FicarY, cor, false) 
		_, _, menorTomadaAdversario := JogadaObrigatoria(tabTemp, Inverter(cor)) 
		
		for i:=1; i < MAX_MOVIMENTOS && movimentos[i] != nil; i++ {
			tabTemp = tabuleiro.Copy()
			tabTemp.MoverPeca(movimentos[i].X, movimentos[i].Y, movimentos[i].FicarX, movimentos[i].FicarY, cor, false)
			_, _, tomadaAdversario := JogadaObrigatoria(tabTemp, Inverter(cor))
			
			
			if(tomadaAdversario == menorTomadaAdversario){ 
				if(tabTemp.ViraDama(movimentos[i].FicarX, movimentos[i].FicarY, cor)){
					if(viraDama){
						if((cor == Preto && melhorMovimento.X < movimentos[i].X) || (cor == Vermelho && melhorMovimento.X > movimentos[i].X)){
							  melhorMovimento = movimentos[i]
						}
					}else{
						melhorMovimento = movimentos[i]
						viraDama = true
					}
				}
			}else{
				if(tomadaAdversario < menorTomadaAdversario){
					menorTomadaAdversario = tomadaAdversario
					melhorMovimento = movimentos[i]
				}
			}
		}
		
		//Realiza o melhor movimento
		tabuleiro.MoverPeca(melhorMovimento.X, melhorMovimento.Y, melhorMovimento.FicarX, melhorMovimento.FicarY, cor, false)
		tabuleiro.ViraDama(melhorMovimento.FicarX, melhorMovimento.FicarY, cor)
		return false		
	}
}


